// schema/peer.js
import mongoose from "mongoose";

const peerSchema = new mongoose.Schema(
  {
    userId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: "User",
      required: true,
      index: true,
    },
    username: {
      type: String,
      required: true,
    },
    infoHash: {
      type: String,
      required: true,
      index: true,
    },
    peerId: {
      type: String,
      required: true,
      index: true,
    },
    ip: {
      type: String,
      required: true,
      validate: {
        validator: function(v) {
          // 支持 IPv4 和 IPv6-mapped IPv4 地址
          // 纯 IPv4: 192.168.1.1
          const ipv4Pattern = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
          // IPv6-mapped IPv4: ::ffff:192.168.1.1
          const ipv6MappedPattern = /^::ffff:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i;
          
          return ipv4Pattern.test(v) || ipv6MappedPattern.test(v);
        },
        message: 'Invalid IP address format'
      }
    },
    port: {
      type: Number,
      required: true,
      min: 1,
      max: 65535,
    },
    uploaded: {
      type: Number,
      default: 0,
      min: 0,
    },
    downloaded: {
      type: Number,
      default: 0,
      min: 0,
    },
    left: {
      type: Number,
      default: 0,
      min: 0,
    },
    client: {
      type: String,
      default: "Unknown Client",
    },
    userAgent: {
      type: String,
      default: "",
    },
    lastAnnounce: {
      type: Date,
      default: Date.now,
      index: true,
    },
    isSeeder: {
      type: Boolean,
      default: false,
      index: true,
    },
    // 首次 announce 时间
    firstAnnounce: {
      type: Date,
      default: Date.now,
    },
    // announce 次数
    announceCount: {
      type: Number,
      default: 1,
    },
  },
  {
    timestamps: true,
    // 复合索引，用于高效查询
    indexes: [
      { infoHash: 1, lastAnnounce: -1 }, // 按种子和最后活跃时间查询
      { userId: 1, infoHash: 1 }, // 按用户和种子查询
      { peerId: 1, infoHash: 1 }, // 按 peer ID 和种子查询（唯一性）
      { infoHash: 1, isSeeder: 1, lastAnnounce: -1 }, // 按种子类型查询活跃的 seeders/leechers
    ],
  }
);

// 复合唯一索引：每个种子的每个用户只能有一个 peer 记录
peerSchema.index({ userId: 1, infoHash: 1, peerId: 1 }, { unique: true });

// 虚拟字段：计算 peer 的活跃状态
peerSchema.virtual("isActive").get(function () {
  const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);
  return this.lastAnnounce > oneHourAgo;
});

// 虚拟字段：计算上传下载比率
peerSchema.virtual("ratio").get(function () {
  if (this.downloaded === 0) {
    return this.uploaded > 0 ? Infinity : 0;
  }
  return this.uploaded / this.downloaded;
});

// 虚拟字段：计算完成百分比
peerSchema.virtual("progress").get(function () {
  const total = this.downloaded + this.left;
  if (total === 0) return 100;
  return (this.downloaded / total) * 100;
});

// 静态方法：获取种子的活跃统计
peerSchema.statics.getTorrentStats = async function (infoHash) {
  const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);

  return await this.aggregate([
    {
      $match: {
        infoHash,
        lastAnnounce: { $gt: oneHourAgo },
      },
    },
    {
      $group: {
        _id: null,
        totalPeers: { $sum: 1 },
        seeders: { $sum: { $cond: [{ $eq: ["$left", 0] }, 1, 0] } },
        leechers: { $sum: { $cond: [{ $gt: ["$left", 0] }, 1, 0] } },
        totalUploaded: { $sum: "$uploaded" },
        totalDownloaded: { $sum: "$downloaded" },
        avgProgress: {
          $avg: {
            $cond: [
              { $gt: [{ $add: ["$downloaded", "$left"] }, 0] },
              {
                $multiply: [
                  {
                    $divide: [
                      "$downloaded",
                      { $add: ["$downloaded", "$left"] },
                    ],
                  },
                  100,
                ],
              },
              0,
            ],
          },
        },
      },
    },
  ]);
};

// 静态方法：清理过期的 peers
peerSchema.statics.cleanExpired = async function (maxAge = 60 * 60 * 1000) {
  const expireTime = new Date(Date.now() - maxAge);
  const result = await this.deleteMany({
    lastAnnounce: { $lt: expireTime },
  });
  return result.deletedCount;
};

// 静态方法：获取活跃的 peers 列表
peerSchema.statics.getActivePeers = async function (
  infoHash,
  excludePeerId = null,
  limit = 50
) {
  const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);

  const query = {
    infoHash,
    lastAnnounce: { $gt: oneHourAgo },
  };

  if (excludePeerId) {
    query.peerId = { $ne: excludePeerId };
  }

  return await this.find(query).sort({ lastAnnounce: -1 }).limit(limit).lean();
};

// 实例方法：更新 announce 信息
peerSchema.methods.updateAnnounce = function (announceData) {
  this.ip = announceData.ip || this.ip;
  this.port = announceData.port || this.port;
  this.uploaded = announceData.uploaded || this.uploaded;
  this.downloaded = announceData.downloaded || this.downloaded;
  this.left = announceData.left !== undefined ? announceData.left : this.left;
  this.isSeeder = this.left === 0;
  this.lastAnnounce = new Date();
  this.announceCount += 1;

  if (announceData.client) {
    this.client = announceData.client;
  }

  if (announceData.userAgent) {
    this.userAgent = announceData.userAgent;
  }

  return this.save();
};

// 中间件：在保存前自动设置 isSeeder
peerSchema.pre("save", function (next) {
  this.isSeeder = this.left === 0;
  next();
});

// 中间件：在更新前自动设置 isSeeder
peerSchema.pre(['findOneAndUpdate', 'updateOne', 'updateMany'], function(next) {
  const update = this.getUpdate();
  if (update.$set && update.$set.left !== undefined) {
      update.$set.isSeeder = update.$set.left === 0;
  }
  next();
});

const Peer = mongoose.model("Peer", peerSchema);

export default Peer;
